在Java程式開發中,輸入輸出(IO)操作扮演著關鍵角色。無論是處理檔案、進行網路通訊,還是與使用者互動,Java的IO系統都是不可或缺的工具。
串流(Stream)為處理資料的輸入和輸出提供統一且靈活的框架。它的核心理念是將各種不同的資料來源——例如檔案、網路連接、記憶體緩衝區等——抽象化為連續的資料流,抽象化簡化資料處理的過程,使得開發者可以用一致的方式處理不同類型的資料來源。
在Java程式設計中,串流是一個抽象的概念,代表一個連續的資料流。
這個資料流可以是從程式到外部資源(如檔案或網路連接),也可以是從外部資源到程式。
串流提供一種統一的方式來處理輸入和輸出操作,無論底層的資料來源或目的地是什麼。
串流在Java的IO系統中扮演著關鍵角色:
抽象化:串流將各種不同的輸入輸出源抽象化,使得程式設計師可以用一致的方式處理不同類型的資料。
彈性:Java提供多種不同類型的串流,可以根據需求選擇最適合的串流類型。
效能:某些串流類型(如緩衝串流)可以提高IO操作的效能。
資料轉換:串流可以進行資料的轉換,例如將位元資料轉換為字元資料。
在Java的IO系統中,串流主要分為兩大類:位元串流和字元串流。
位元串流用於處理位元資料,也就是8位元組(byte)為單位的資料,適合處理二進位檔案,如圖片、音訊、視訊等。
主要的位元串流類別包括:
字元串流專門用於處理字元資料,以 16 位元的 Unicode 字元為單位,適合處理文字檔案或其他字元based的資料。
主要的字元串流類別包括:
選擇使用哪種串流取決於您處理的資料類型。如果您在處理文字資料,使用字元串流會更方便;如果處理二進位資料或不確定資料類型,使用位元串流會更安全。
在Java的IO系統中,串流根據資料流向可以分為輸入串流和輸出串流。
輸入串流用於從資料源讀取資料到程式中。常見的輸入串流類別包括:
輸出串流用於將資料從程式寫入到目標位置。常見的輸出串流類別包括:
以下是使用FileInputStream和FileOutputStream進行檔案讀寫的簡單示例:
import java.io.*;
public class FileIOExample {
public static void main(String[] args) {
// 檔案讀取
try (FileInputStream fis = new FileInputStream("input.txt")) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
// 檔案寫入
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String data = "這是要寫入檔案的內容";
byte[] byteArray = data.getBytes();
fos.write(byteArray);
System.out.println("資料已成功寫入檔案");
} catch (IOException e) {
e.printStackTrace();
}
}
}
緩衝串流是Java IO系統中一個重要的概念,通過在記憶體中設置緩衝區來提高IO操作的效能。
緩衝串流可以減少實際的物理讀寫次數,從而顯著提升IO操作的速度。
緩衝串流在讀取或寫入資料時,會先將資料暫存在一個記憶體緩衝區中。
當緩衝區滿(在寫入時)或空(在讀取時),才會進行實際的IO操作,可以減少與底層系統的交互次數,提高效能。
主要優勢包括:
這兩個類別是位元緩衝串流,用於處理位元資料。
這兩個類別是字元緩衝串流,用於處理字元資料。
以下是一個使用緩衝串流進行檔案複製的例子,展示如何使用緩衝串流來提高IO操作的效能:
import java.io.*;
public class BufferedStreamExample {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("destination.txt"))) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
System.out.println("檔案複製完成");
} catch (IOException e) {
e.printStackTrace();
}
}
}
物件串流是Java IO系統中的一個重要組成部分,允許我們將整個Java物件寫入串流或從串流中讀取,被稱為序列化(將物件轉換為位元序列)和反序列化(將位元序列轉換回物件)。
序列化是將物件的狀態轉換為可以儲存或傳輸的形式的過程。
反序列化則是將這種形式轉換回物件的過程。這兩個過程使得我們可以輕鬆地儲存物件狀態,或在網路上傳輸物件。
要使一個類別可序列化,必須實作 java.io.Serializable 介面。這是一個標記介面,不需要實作任何方法。
Java提供兩個特殊的串流類別來處理物件的序列化和反序列化:
以下是一個使用物件串流進行序列化和反序列化的例子:
import java.io.*;
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
public class ObjectStreamExample {
public static void main(String[] args) {
Person person = new Person("張三", 30);
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
oos.writeObject(person);
System.out.println("物件已序列化");
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person deserializedPerson = (Person) ois.readObject();
System.out.println("反序列化的物件: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
使用物件串流時需要注意以下幾點:
物件串流為Java程式提供一種方便的方式來儲存和傳輸複雜的資料結構,但使用時需要注意安全性和版本控制等問題。
資料串流是Java IO系統中的一種特殊串流,專門用於讀寫Java基本資料類型和字串,提供處理二進位格式的基本資料類型,而不需要手動進行位元組轉換。
Java提供兩個主要的資料串流類別:
這兩個類別提供一系列方法來讀寫不同的資料類型,如readInt()、writeDouble()、readUTF()、writeBoolean()等。
以下是一個使用DataInputStream和DataOutputStream進行基本資料類型讀寫的例子:
import java.io.*;
public class DataStreamExample {
public static void main(String[] args) {
// 寫入資料
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin"))) {
dos.writeInt(100);
dos.writeDouble(3.14159);
dos.writeBoolean(true);
dos.writeUTF("你好,世界!");
System.out.println("資料已寫入檔案");
} catch (IOException e) {
e.printStackTrace();
}
// 讀取資料
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.bin"))) {
int intValue = dis.readInt();
double doubleValue = dis.readDouble();
boolean booleanValue = dis.readBoolean();
String stringValue = dis.readUTF();
System.out.println("讀取的整數: " + intValue);
System.out.println("讀取的浮點數: " + doubleValue);
System.out.println("讀取的布林值: " + booleanValue);
System.out.println("讀取的字串: " + stringValue);
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用資料串流時需要注意以下幾點:
資料串流在處理二進位格式的資料時非常有用,特別是在需要精確控制資料格式的場景中,如網路通訊或自定義檔案格式。
印表機串流是Java IO系統中用於輸出格式化文字的特殊串流,提供輸出各種資料類型,並且可以自動處理格式化。
Java提供兩個主要的印表機串流類別:
這兩個類別都提供print()、println()和format()等方法,可以方便地輸出格式化的文字。
在Java中,我們經常使用System.out來輸出資訊到控制台。實際上,System.out就是一個PrintStream物件。
這就是為什麼我們可以直接使用System.out.println()來輸出各種類型的資料。
以下是一個簡單的使用PrintStream和PrintWriter的例子:
import java.io.*;
public class PrintStreamExample {
public static void main(String[] args) {
// 使用 PrintStream
try (PrintStream ps = new PrintStream(new FileOutputStream("output.txt"))) {
ps.println("這是使用 PrintStream 輸出的文字");
ps.printf("格式化輸出:%d, %f, %s%n", 10, 3.14, "Hello");
} catch (IOException e) {
e.printStackTrace();
}
// 使用 PrintWriter
try (PrintWriter pw = new PrintWriter(new FileWriter("output2.txt"))) {
pw.println("這是使用 PrintWriter 輸出的文字");
pw.printf("格式化輸出:%d, %f, %s%n", 20, 2.718, "World");
} catch (IOException e) {
e.printStackTrace();
}
}
}
印表機串流的主要優點是:
在開發過程中,當需要輸出格式化的文字或日誌時,印表機串流是一個非常有用的工具。
在使用Java IO串流時,有一些最佳實踐和注意事項可以幫助我們更有效地進行IO操作,並避免常見的錯誤。
在使用完串流後,務必要正確關閉。未關閉的串流可能會導致資源洩漏,影響程式的效能和穩定性。
Java 7 引入的 try-with-resources 語法是一種自動資源管理的方式,可以確保串流在使用後被正確關閉。例如:
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
// 使用串流進行操作
} catch (IOException e) {
e.printStackTrace();
}
使用這種語法,即使在發生異常的情況下,串流也會被正確關閉。
使用緩衝串流:對於大量的IO操作,使用緩衝串流可以顯著提高效能。
適當的緩衝區大小:根據實際情況選擇合適的緩衝區大小,過大或過小都可能影響效能。
避免頻繁的小規模IO:盡量批量讀寫,減少IO操作的次數。
使用NIO:對於需要高效能的場景,考慮使用Java NIO(New IO)。
妥善處理IO異常,不要忽視或吞掉異常。正確的異常處理可以幫助診斷和解決問題。
在處理文字檔案時,要注意字元編碼問題。明確指定編碼可以避免出現亂碼:
try (BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("file.txt"), "UTF-8"))) {
// 讀取檔案內容
}
根據實際需求選擇合適的串流類型。例如,對於文字處理,使用字元串流;對於二進位資料,使用位元串流。
本篇文章同步刊載: JYI.TW
筆者個人的網站: JUNYI